Skip to content

Conversation

@malavikasamak
Copy link
Contributor

The -Wunsafe-buffer-usage analysis currently warns when a const sized array is safely accessed, with an index that is bound by the remainder operator. The false alarm is now suppressed.

Example:

int circular_buffer(int array[10], uint idx) {
return array[idx %10]; // Safe operation
}

rdar://148443453

… accessed array [idx %const]

The -Wunsafe-buffer-usage analysis currently warns when a const sized array is safely accessed,
with an index that is bound by the remainder operator. The false alarm is now suppressed.

Example:

int circular_buffer(int array[10], uint idx) {
   return array[idx %10]; // Safe operation
}

rdar://148443453
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:analysis labels May 15, 2025
@llvmbot
Copy link
Member

llvmbot commented May 15, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Malavika Samak (malavikasamak)

Changes

The -Wunsafe-buffer-usage analysis currently warns when a const sized array is safely accessed, with an index that is bound by the remainder operator. The false alarm is now suppressed.

Example:

int circular_buffer(int array[10], uint idx) {
return array[idx %10]; // Safe operation
}

rdar://148443453


Full diff: https://github.com/llvm/llvm-project/pull/140113.diff

2 Files Affected:

  • (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+16-1)
  • (modified) clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp (+9-1)
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 5b72382ca9772..2f669637a2731 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -600,12 +600,27 @@ static bool isSafeArraySubscript(const ArraySubscriptExpr &Node,
   } else if (const auto *BE = dyn_cast<BinaryOperator>(IndexExpr)) {
     // For an integer expression `e` and an integer constant `n`, `e & n` and
     // `n & e` are bounded by `n`:
-    if (BE->getOpcode() != BO_And)
+    if (BE->getOpcode() != BO_And && BE->getOpcode() != BO_Rem)
       return false;
 
     const Expr *LHS = BE->getLHS();
     const Expr *RHS = BE->getRHS();
 
+    if(BE->getOpcode() == BO_Rem) {
+      // If n is a negative number, then n % const can be greater than const
+      if(!LHS->getType()->isUnsignedIntegerType()) {
+        return false;
+      }
+
+      if(!RHS->isValueDependent() && RHS->EvaluateAsInt(EVResult, Ctx)) {
+        llvm::APSInt result = EVResult.Val.getInt();
+        if (result.isNonNegative() && result.getLimitedValue() <= limit)
+          return true;
+      }
+
+      return false;
+    }
+
     if ((!LHS->isValueDependent() &&
          LHS->EvaluateAsInt(EVResult, Ctx)) || // case: `n & e`
         (!RHS->isValueDependent() &&
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 3233999ea8ea2..b2358bb9f6be3 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -35,7 +35,15 @@ void constant_idx_safe0(unsigned idx) {
   buffer[0] = 0;
 }
 
-int array[10]; // expected-warning {{'array' is an unsafe buffer that does not perform bounds checks}}
+int array[10]; // expected-warning 2{{'array' is an unsafe buffer that does not perform bounds checks}}
+
+void circular_access_safe(unsigned idx) {
+  array[idx % 10];
+}
+
+void circular_access_unsafe(int idx) {
+  array[idx % 10]; // expected-note {{used in buffer access here}}
+}
 
 void masked_idx1(unsigned long long idx, Foo f) {
   // Bitwise and operation

@malavikasamak malavikasamak requested a review from Copilot May 15, 2025 17:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes false warnings triggered by the -Wunsafe-buffer-usage analysis when a const sized array is safely accessed using the modulo operator.

  • Updated test expectations in warn-unsafe-buffer-usage-array.cpp to account for dual warnings and added new test functions for circular access.
  • Extended and refined the safety check logic in UnsafeBufferUsage.cpp to correctly handle the BO_Rem operator for remainder operations.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp Updated test comments and added test functions for safe and unsafe circular array access.
clang/lib/Analysis/UnsafeBufferUsage.cpp Modified the safety check to allow BO_Rem and added specific handling for unsigned types.

}

int array[10]; // expected-warning {{'array' is an unsafe buffer that does not perform bounds checks}}
int array[10]; // expected-warning 2{{'array' is an unsafe buffer that does not perform bounds checks}}
Copy link

Copilot AI May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure that the update from a single expected warning to two is intentional and that the test comment clearly communicates the new warning count rationale.

Copilot uses AI. Check for mistakes.

if(!RHS->isValueDependent() && RHS->EvaluateAsInt(EVResult, Ctx)) {
llvm::APSInt result = EVResult.Val.getInt();
if (result.isNonNegative() && result.getLimitedValue() <= limit)
Copy link

Copilot AI May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding a comment to explain the purpose and derivation of the 'limit' variable to enhance clarity on how it determines the safe boundary for remainder operations.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented May 15, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@malavikasamak
Copy link
Contributor Author

CC @dtarditi

Copy link
Contributor

@ziqingluo-90 ziqingluo-90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

(AI comments in this PR aren't very helpful IMO 😅)

@malavikasamak malavikasamak merged commit 3931566 into llvm:main May 17, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:analysis clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants